/*
## @file
#
#  Copyright (c) 2018 Loongson Technology Corporation Limited (www.loongson.cn).
#  All intellectual property rights(Copyright, Patent and Trademark) reserved.
#
#  Any violations of copyright or other intellectual property rights of the Loongson Technology
#  Corporation Limited will be held accountable in accordance with the law,
#  if you (or any of your subsidiaries, corporate affiliates or agents) initiate
#  directly or indirectly any Intellectual Property Assertion or Intellectual Property Litigation:
#  (i) against Loongson Technology Corporation Limited or any of its subsidiaries or corporate affiliates,
#  (ii) against any party if such Intellectual Property Assertion or Intellectual Property Litigation arises
#  in whole or in part from any software, technology, product or service of Loongson Technology Corporation
#  Limited or any of its subsidiaries or corporate affiliates, or (iii) against any party relating to the Software.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
#  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR
#  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION).
#
#
##
*/


#define DQ_CHANGE_WITH_DQS
#define MC_MULTI_CHANNEL  //TODO

#define DLL_VALVE_CK_OFFSET         0x32
#define DDR3_INIT_START_OFFSET      0x18

#define WRDQ_LT_HALF_OFFSET         0x20
#define WRDQS_LT_HALF_OFFSET        0x21
#define RDDQS_LT_HALF_OFFSET        0x22
#define RDDATA_DELAY_OFFSET         0x23
#define RDOE_BEGIN_OFFSET           0x2e
#define RDOE_END_OFFSET             0x2f
#define RDOE_START_OFFSET           0x2c
#define RDOE_STOP_OFFSET            0x2d
#define RDODT_BEGIN_OFFSET          0x32
#define RDODT_END_OFFSET            0x33
#define RDODT_START_OFFSET          0x30
#define RDODT_STOP_OFFSET           0x31
#define WRDQ_CLKDELAY_OFFSET        0x34
#define DDR3_DLL_GATE_OFFSET        0x38
#define DDR3_DLL_WRDQ_OFFSET        0x39
#define DDR3_DLL_WRDQS_OFFSET       0x3a

#define DDR3_DDR2__MODE_OFFSET      0x160
#define DDR3_DRAM_INIT_OFFSET       0x163
#define CS_ENABLE_OFFSET            0x168
#define CS_MRS_OFFSET               0x169
#define CS_ZQ_OFFSET                0x16a
#define BURST_LENGTH_OFFSET         0x16c
#define ADDR_MIRROR_OFFSET          0x16e

#define COL_DIFF_OFFSET             0x210
#define BA_DIFF_OFFSET              0x211
#define ROW_DIFF_OFFSET             0x212
#define CS_DIFF_OFFSET              0x213
#define ADDR_WIN_OFFSET             0x214


#define ODT_MAP_OFFSET              0x170
#define ECC_ENABLE_OFFSET           0x252
#define ECC_INT_ENABLE_OFFSET       0x250
#define ADDR_INFO_CS_0_OFFSET       0x210
#define ADDR_INFO_CS_1_OFFSET       0x218
#define ADDR_INFO_CS_2_OFFSET       0x220
#define ADDR_INFO_CS_3_OFFSET       0x228

#define CMD_TIMING_OFFSET           0x161
#define tRDDATA_OFFSET              0x1c0
#define VERSION_OFFSET              0x0
#define BANK_OFFSET                 0x16b

#define DDR3_LVL_CS_OFFSET          0x183
#define DDR3_LVL_MODE_OFFSET        0x180
#define DDR3_LVL_REQ_OFFSET         0x181
#define DDR3_LVL_READY_OFFSET       0x185
#define DDR3_LVL_DONE_OFFSET        0x186
#define DDR3_LVL_RESP_OFFSET        0x187

#define tPHY_RDDATA_OFFSET          0x1c0
#define tPHY_WRLAT_OFFSET           0x1d4
#define tRFC_OFFSET                 0x1ca
#define tREF_OFFSET                 0x1cb

#define WLVL_CHECK_BIT              0x01
#define GLVL_CHECK_BIT              0x3
#define WLVL_FILTER_LEN             0x5
#define GLVL_FILTER_LEN             0x5
#define DLL_WRDQ_SUB                0x20
#define DLL_GATE_SUB                0x20
#define DLL_ADJ_RANGE               0x8
#define WRDQ_LT_HALF_STD            0x40
#define WRDQS_LT_HALF_STD           0x40
#define RDDQS_LT_HALF_STD1          0x3A
#define RDDQS_LT_HALF_STD2          0x10
#define PREAMBLE_LEN                0x60

#define CS_MAP_OFFSET               0x1f4

#define BURST_LENGTH                8

#define DRAM_TYPE_OFFSET            0x2
#define DDR2                        0x8
#define DDR3                        0xb
#define DDR4                        0xc

#define MODULE_TYPE_OFFSET          0x3
#define RDIMM                       0x1
#define UDIMM                       0x2
#define SODIMM                      0x3

#define DRAM_DEN_BANK_OFFSET        0x4
#define DRAM_DEN_OFFSET             0x0
#define DRAM_DEN_BIT                0xf
#define DRAM_DEN_256Mb              0x0
#define DRAM_DEN_512Mb              0x1
#define DRAM_DEN_1Gb                0x2
#define DRAM_DEN_2Gb                0x3
#define DRAM_DEN_4Gb                0x4
#define DRAM_DEN_8Gb                0x5
#define DRAM_DEN_16Gb               0x6
#define DRAM_BANK_OFFSET            0x4
#define DRAM_BANK_BIT               0x7
#define BANK_8                      0x0
#define BANK_16                     0x1

#define DRAM_ADDR_OFFSET            0x5
#define DRAM_COL_OFFSET             0x0
#define DRAM_COL_BIT                0x7
#define DRAM_COL_9                  0x0
#define DRAM_COL_10                 0x1
#define DRAM_COL_11                 0x2
#define DRAM_COL_12                 0x3
#define DRAM_ROW_OFFSET             0x3
#define DRAM_ROW_BIT                0x7
#define DRAM_ROW_12                 0x0
#define DRAM_ROW_13                 0x1
#define DRAM_ROW_14                 0x2
#define DRAM_ROW_15                 0x3
#define DRAM_ROW_16                 0x4

#define MODULE_ORG_OFFSET           0x7
#define DRAM_WIDTH_OFFSET           0x0
#define DRAM_WIDTH_BIT              0x7
#define DRAM_X4                     0x0
#define DRAM_X8                     0x1
#define DRAM_X16                    0x2
#define DRAM_X32                    0x3
#define MODULE_RANK_OFFSET          0x3
#define MODULE_RANK_BIT             0x7
#define MODULE_RANK_1               0x0
#define MODULE_RANK_2               0x1
#define MODULE_RANK_3               0x2
#define MODULE_RANK_4               0x3

#define MODULE_BUS_WIDTH_OFFSET     0x8
#define MODULE_WIDTH_OFFSET         0x0
#define MODULE_WIDTH_BIT            0x7
#define MODULE_WIDTH64              0x3
#define MODULE_WIDTH32              0x2
#define MODULE_WIDTH16              0x1
#define MODULE_WIDTH8               0x0

#define DDR4_MODULE_TYPE_OFFSET                 0x3
#define DDR4_MODULE_BASE_MODULE_TYPE_BITS_OFFSET        0x0
#define DDR4_MODULE_BASE_MODULE_TYPE_BITS_MASK          0xF

#define DDR4_SDRAM_DENSITY_AND_BANKS_OFFSET     0x4
#define DDR4_SDRAM_BANK_ADDRESS_BITS_OFFSET             0x4
#define DDR4_SDRAM_BANK_ADDRESS_BITS_MASK               0x3

#define DDR4_SDRAM_BANK_GROUP_BITS_OFFSET               0x6
#define DDR4_SDRAM_BANK_GROUP_BITS_MASK                 0x3

#define DDR4_SDRAM_TOTAL_CAPACITY_BITS_OFFSET           0x0
#define DDR4_SDRAM_TOTAL_CAPACITY_BITS_MASK             0xF

#define DDR4_SDRAM_ADDRESSING_OFFSET            0x5
#define DDR4_ROW_ADDRESSING_BITS_OFFSET                 0x3
#define DDR4_ROW_ADDRESSING_BITS_MASK                   0x7

#define DDR4_COLUMN_ADDRESSING_BITS_OFFSET              0x0
#define DDR4_COLUMN_ADDRESSING_BITS_MASK                0x7

#define DDR4_MODULE_NOMINAL_VOLTAGE_OFFSET      0xB
#define DDR4_MODULE_NOMINAL_VOLTAGE_BITS_OFFSET         0x0
#define DDR4_MODULE_NOMINAL_VOLTAGE_BITS_MASK           0x3

#define DDR4_MODULE_ORG_OFFSET                  0xC
#define DDR4_MODULE_ORG_SDRAM_DEVICE_WIDTH_BITS_OFFSET  0x0
#define DDR4_MODULE_ORG_SDRAM_DEVICE_WIDTH_BITS_MASK    0x7

#define DDR4_MODULE_ORG_SDRAM_NUMBER_RANKS_BITS_OFFSET  0x3
#define DDR4_MODULE_ORG_SDRAM_NUMBER_RANKS_BITS_MASK    0x7

#define DDR4_MODULE_MEM_BUS_WIDTH_OFFSET        0xD
#define DDR4_MODULE_MEM_PRIMARY_BUS_WIDTH_BITS_OFFSET   0x0
#define DDR4_MODULE_MEM_PRIMARY_BUS_WIDTH_BITS_MASK     0x7

#define DDR4_MODULE_MEM_BUS_WIDTH_EXTENSION_BITS_OFFSET 0x3
#define DDR4_MODULE_MEM_BUS_WIDTH_EXTENSION_BITS_MASK   0x3

#define DDR4_MODULE_MODULE_MANUFACTURER_FIRST_OFFSET  0x140
#define DDR4_MODULE_MODULE_MANUFACTURER_SEC_OFFSET    0x141
#define DDR4_MODULE_MANUFACTURER_LEN                  0x2

#define DDR4_MODULE_SERIAL_NUMBER_BASE_OFFSET   0x145
#define DDR4_MODULE_SERIAL_NUMBER1_OFFSET       0x146
#define DDR4_MODULE_SERIAL_NUMBER2_OFFSET       0x147
#define DDR4_MODULE_SERIAL_NUMBER3_OFFSET       0x148
#define DDR4_MODULE_SERIAL_NUMBER_LEN           0x4

#define DDR4_MODULE_PART_NUMBER_BASE_OFFSET     0x149
#define DDR4_MODULE_PART_NUMBER1_OFFSET         0x14a
#define DDR4_MODULE_PART_NUMBER2_OFFSET         0x14b
#define DDR4_MODULE_PART_NUMBER3_OFFSET         0x14c
#define DDR4_MODULE_PART_NUMBER4_OFFSET         0x14d
#define DDR4_MODULE_PART_NUMBER5_OFFSET         0x14e
#define DDR4_MODULE_PART_NUMBER6_OFFSET         0x14f
#define DDR4_MODULE_PART_NUMBER7_OFFSET         0x150
#define DDR4_MODULE_PART_NUMBER8_OFFSET         0x151
#define DDR4_MODULE_PART_NUMBER9_OFFSET         0x152
#define DDR4_MODULE_PART_NUMBERa_OFFSET         0x153
#define DDR4_MODULE_PART_NUMBERb_OFFSET         0x154
#define DDR4_MODULE_PART_NUMBERc_OFFSET         0x155
#define DDR4_MODULE_PART_NUMBERd_OFFSET         0x156
#define DDR4_MODULE_PART_NUMBERe_OFFSET         0x157
#define DDR4_MODULE_PART_NUMBERf_OFFSET         0x158
#define DDR4_MODULE_PART_NUMBER10_OFFSET        0x159
#define DDR4_MODULE_PART_NUMBER11_OFFSET        0x15a
#define DDR4_MODULE_PART_NUMBER12_OFFSET        0x15b
#define DDR4_MODULE_PART_NUMBER13_OFFSET        0x15c
#define DDR4_MODULE_PART_NUMBER_LEN             0x14

#define DDR3_MODULE_TYPE_OFFSET                 0x3
#define DDR3_MODULE_BASE_MODULE_TYPE_BITS_OFFSET        0x0
#define DDR3_MODULE_BASE_MODULE_TYPE_BITS_MASK          0xF

#define DDR3_SDRAM_DENSITY_AND_BANKS_OFFSET     0x4

#define DDR3_SDRAM_TOTAL_CAPACITY_BITS_OFFSET           0x0
#define DDR3_SDRAM_TOTAL_CAPACITY_BITS_MASK             0xF

#define DDR3_SDRAM_BANK_ADDRESS_BITS_OFFSET             0x4
#define DDR3_SDRAM_BANK_ADDRESS_BITS_MASK               0x3

#define DDR3_SDRAM_ADDRESSING_OFFSET            0x5
#define DDR3_ROW_ADDRESSING_BITS_OFFSET                 0x3
#define DDR3_ROW_ADDRESSING_BITS_MASK                   0x7

#define DDR3_COLUMN_ADDRESSING_BITS_OFFSET              0x0
#define DDR3_COLUMN_ADDRESSING_BITS_MASK                0x7

#define DDR3_MODULE_NOMINAL_VOLTAGE_OFFSET      0x6
#define DDR3_MODULE_NOMINAL_VOLTAGE_BITS_OFFSET         0x0
#define DDR3_MODULE_NOMINAL_VOLTAGE_BITS_MASK           0x7

#define DDR3_MODULE_ORG_OFFSET                  0x7
#define DDR3_MODULE_ORG_SDRAM_DEVICE_WIDTH_BITS_OFFSET  0x0
#define DDR3_MODULE_ORG_SDRAM_DEVICE_WIDTH_BITS_MASK    0x7

#define DDR3_MODULE_ORG_SDRAM_NUMBER_RANKS_BITS_OFFSET  0x3
#define DDR3_MODULE_ORG_SDRAM_NUMBER_RANKS_BITS_MASK    0x7

#define DDR3_MODULE_MEM_BUS_WIDTH_OFFSET        0x8
#define DDR3_MODULE_MEM_PRIMARY_BUS_WIDTH_BITS_OFFSET   0x0
#define DDR3_MODULE_MEM_PRIMARY_BUS_WIDTH_BITS_MASK     0x7

#define DDR3_MODULE_MEM_BUS_WIDTH_EXTENSION_BITS_OFFSET 0x3
#define DDR3_MODULE_MEM_BUS_WIDTH_EXTENSION_BITS_MASK   0x3

#define DDR3_MODULE_MODULE_MANUFACTURER_FIRST_OFFSET 117
#define DDR3_MODULE_MODULE_MANUFACTURER_SEC_OFFSET   118
#define DDR3_MODULE_MANUFACTURER_LEN                    0x2

#define DDR3_MODULE_SERIAL_NUMBER_BASE_OFFSET   122
#define DDR3_MODULE_SERIAL_NUMBER1_OFFSET       123
#define DDR3_MODULE_SERIAL_NUMBER2_OFFSET       124
#define DDR3_MODULE_SERIAL_NUMBER3_OFFSET       125
#define DDR3_MODULE_SERIAL_NUMBER_LEN           0x4

#define DDR3_MODULE_PART_NUMBER_BASE_OFFSET     128
#define DDR3_MODULE_PART_NUMBER1_OFFSET         129
#define DDR3_MODULE_PART_NUMBER2_OFFSET         130
#define DDR3_MODULE_PART_NUMBER3_OFFSET         131
#define DDR3_MODULE_PART_NUMBER4_OFFSET         132
#define DDR3_MODULE_PART_NUMBER5_OFFSET         133
#define DDR3_MODULE_PART_NUMBER6_OFFSET         134
#define DDR3_MODULE_PART_NUMBER7_OFFSET         135
#define DDR3_MODULE_PART_NUMBER8_OFFSET         136
#define DDR3_MODULE_PART_NUMBER9_OFFSET         137
#define DDR3_MODULE_PART_NUMBERa_OFFSET         138
#define DDR3_MODULE_PART_NUMBERb_OFFSET         139
#define DDR3_MODULE_PART_NUMBERc_OFFSET         140
#define DDR3_MODULE_PART_NUMBERd_OFFSET         141
#define DDR3_MODULE_PART_NUMBERe_OFFSET         142
#define DDR3_MODULE_PART_NUMBERf_OFFSET         143
#define DDR3_MODULE_PART_NUMBER10_OFFSET        144
#define DDR3_MODULE_PART_NUMBER11_OFFSET        145
#define DDR3_MODULE_PART_NUMBER_LEN             18

#define MODULE_ECC_OFFSET           0x3
#define MODULE_ECC_BIT              0x3
#define MODULE_ECC_INCLUDE          0x1

#define MIRROR_OFFSET               0x3f
#define MIRROR_SUPPORT              0x1
#define MC_REGS_COUNT               118

#define RAW_CARD_BIT                0x1f
#define RAW_CARD_OFFSET             0x3e
#define RAW_CARD_VERSION_F          0x05

//define offset accroding to s1 definition as below
#define S1_CID_NUM_OFFSET_V1        46
#define S1_BG_NUM_OFFSET_V1         44
#define S1_BA_NUM_OFFSET_V1         43
#define S1_ROW_SIZE_OFFSET_V1       40
#define S1_COL_SIZE_OFFSET_V1       38
#define S1_ADDR_MIRROR_OFFSET_V1    37
#define S1_DIMM_MEMSIZE_OFFSET_V1   25
#define S1_DIMM_WIDTH_OFFSET_V1     23
#define S1_DIMM_ECC_OFFSET_V1       22
#define S1_DIMM_TYPE_OFFSET_V1      21
#define S1_SDRAM_WIDTH_OFFSET_V1    19
#define S1_SDRAM_TYPE_OFFSET_V1     16
#define S1_MC_CS_MAP_OFFSET_V1      8
#define S1_I2C_ADDR_OFFSET_V1       4

#define MC_MEMSIZE_MASK_V1 0xfff
#define S1_MC0_MEMSIZE_OFFSET_V1 4
#define S1_MC1_MEMSIZE_OFFSET_V1 16


#ifdef LS3A3000
#define MC_INTERLEAVE_OFFSET        10 //only work when NO_INTERLEAVE is not defined.(32 or above is not tested!!)
#endif
#define MC_INTERLEAVE_BIT           0x14ULL //only work when NO_INTERLEAVE is not defined.(32 or above is not tested!!)

#define DDR_tRDDATA_ADD WriteMcReg8(McRegsBase, tRDDATA_OFFSET, ReadMcReg8(McRegsBase, tRDDATA_OFFSET)+1)
#define DDR_tRDDATA_SUB WriteMcReg8(McRegsBase, tRDDATA_OFFSET, ReadMcReg8(McRegsBase, tRDDATA_OFFSET)-1)

#define INTERLEAVE_10

#define DDR_CFG_BASE  0x900000000ff00000
#define DDR_DAT_BASE  0x9000000000000000
#define CONF_REG_BASE 0x900000001fe20000

//#define LVL_DEBUG
#define ENABLE_DDR_LEVELING
#define ENABLE_MC_VREF_TRAINING
#define ENABLE_DDR_VREF_TRAINING


#define PHY_REG_NUM            72
#define CTL_REG_NUM            280
#define PHY_REG_OFFSET         0x0
#define CTL_REG_OFFSET         0x1000
#define MON_REG_OFFSET         0x2000
#define TST_REG_OFFSET         0x3000
#define DRAM_INIT	       0x010

#define DDR4_DDR3_MODE_OFFSET   0x000c
#define X4_MODE_OFFSET         0x000d
#define DDR4_INIT_START_OFFSET      0x0010
#define DDR4_DRAM_INIT_OFFSET       0x0011
#define RDFIFO_VALID_OFFSET    0x0020
#define PRAMBLE2_OFFSET        0x0021

#define DDR4_DLL_WRDQ_OFFSET    0x0100
#define DDR4_DLL_WRDQS_OFFSET   0x0101
#define DLL_1XGEN_OFFSET       0x0102
#define DLL_1XDLY_OFFSET       0x0103
#define DLL_RDDQS0_OFFSET      0x0108
#define DLL_RDDQS1_OFFSET      0x0109
#define DDR4_DLL_GATE_OFFSET   0x010a
#define DQ_OE_CTRL_OFFSET      0x0110
#define DQS_OE_CTRL_OFFSET     0x0111
#define RDGATE_CTRL_OFFSET     0x0114
#define RDGATE_MODE_OFFSET     0x0115
#define RDGATE_LEN_OFFSET      0x0116
#define RDODT_CTRL_OFFSET      0x0117
#define RDDQS_PHASE_OFFSET     0x0118
#define RDEDGE_SEL_OFFSET      0x0119
#define DLY_2X_OFFSET          0x011a

#define RDQSP_BDLY00_OFFSET    0x0150
#define RDQSP_BDLY01_OFFSET    0x0151
#define RDQSP_BDLY02_OFFSET    0x0152
#define RDQSP_BDLY03_OFFSET    0x0153
#define RDQSP_BDLY04_OFFSET    0x0154
#define RDQSP_BDLY05_OFFSET    0x0155
#define RDQSP_BDLY06_OFFSET    0x0156
#define RDQSP_BDLY07_OFFSET    0x0157
#define RDQSP_BDLY08_OFFSET    0x0158

#define RDQSN_BDLY00_OFFSET    0x0160
#define RDQSN_BDLY01_OFFSET    0x0161
#define RDQSN_BDLY02_OFFSET    0x0162
#define RDQSN_BDLY03_OFFSET    0x0163
#define RDQSN_BDLY04_OFFSET    0x0164
#define RDQSN_BDLY05_OFFSET    0x0165
#define RDQSN_BDLY06_OFFSET    0x0166
#define RDQSN_BDLY07_OFFSET    0x0167
#define RDQSN_BDLY08_OFFSET    0x0168

#define WRDQ_BDLY00_OFFSET     0x0120
#define WRDQS0_BDLY_OFFSET     0x012b

#define DDR4_LVL_MODE_OFFSET   0x0700
#define DDR4_LVL_REQ_OFFSET    0x0701
#define LVL_DLY_OFFSET         0x0702
#define DDR4_LVL_CS_OFFSET     0x0703
#define DDR4_LVL_RDY_OFFSET    0x0708
#define DDR4_LVL_DONE_OFFSET   0x0709

#define DDR4_LVL_RESP_OFFSET   0x0710

#define TPHY_RDDATA_OFFSET     0x1062

#define DLL_VREF_OFFSET        0x00e0
#define VREF_DLY_OFFSET        0x00e1
#define VREF_NUM_OFFSET        0x00e2
#define VREF_SAMPLE_OFFSET     0x00e3
#define VREF_CTRL_DS0_OFFSET   0x0810

#define MR3_CS0_OFFSET         0x1184
#define MR6_CS0_OFFSET         0x118c
#define RDDATA_OFFSET          0x1060
#define BIT_NUM			8
#define SAMPLE_NUM		128
#define N32bit			(SAMPLE_NUM/32)

#define RDDQS_DLL_NUM		32
#define RDQS_BDLY_NUM		16

#define DLL_VALUE_OFFSET	0x0036

//#define USE_MEM_TEST
#define READ_TRAINING_BASE	0x0
#define WRITE_TRAINING_BASE	0x1000000
#define DDR_VREF_TRAINING_BASE	0x2000000

#define READ_TRAINING_TIMES	0x100
#define WRITE_TRAINING_TIMES	0x100
#define DDR_VREF_TRAINING_TIMES 0x100
